unit QuickList_DetailData;

interface

uses
  QuickSortList,
  define_datetime,
  define_stock_quotes;
  
type                    
  {---------------------------------------}
  PDetailDataListItem = ^TDetailDataListItem;
  TDetailDataListItem = record
    DetailDateTime: TDateTimeStock;
    DetailData: PRT_Quote_Detail;
  end;

  {------------------------------------------}
  TDetailDataList = class(TALBaseQuickSortList)    
  public
    function  GetItem(AIndex: Integer): TDateTimeStock;
    procedure SetItem(AIndex: Integer; const AStockDateTime: TDateTimeStock);
    function  GetObject(AIndex: Integer): PRT_Quote_Detail;
    procedure PutObject(AIndex: Integer; ADetailData: PRT_Quote_Detail);
  public
    procedure Notify(Ptr: Pointer; Action: TListNotification); override;
    procedure InsertItem(AIndex: Integer; const AStockDateTime: TDateTimeStock; ADetailData: PRT_Quote_Detail);
    function  CompareItems(const Index1, Index2: Integer): Integer; override;
  public
    function  IndexOf(AStockDateTime: TDateTimeStock): Integer;
    function  IndexOfObject(ADetailData: PRT_Quote_Detail): Integer;
    Function  AddDetailData(const AStockDateTime: TDateTimeStock; ADetailData: PRT_Quote_Detail): Integer;
    function  Find(AStockDateTime: TDateTimeStock; var AIndex: Integer): Boolean;
    procedure InsertObject(AIndex: Integer; const AStockDateTime: TDateTimeStock; ADetailData: PRT_Quote_Detail);
    property  DetailDateTime[Index: Integer]: TDateTimeStock read GetItem write SetItem; default;
    property  DetailData[Index: Integer]: PRT_Quote_Detail read GetObject write PutObject;
  end;
  
implementation

{********************************************************************************}
function TDetailDataList.AddDetailData(const AStockDateTime: TDateTimeStock; ADetailData: PRT_Quote_Detail): Integer;
begin
  if not Sorted then
    Result := FCount
  else if Find(AStockDateTime, Result) then
    case Duplicates of
      lstDupIgnore: Exit;
      lstDupError: Error(@SALDuplicateItem, 0);
    end;
  InsertItem(Result, AStockDateTime, ADetailData);
end;

{*****************************************************************************************}
procedure TDetailDataList.InsertItem(AIndex: Integer; const AStockDateTime: TDateTimeStock; ADetailData: PRT_Quote_Detail);
var
  tmpListItem: PDetailDataListItem;
begin
  New(tmpListItem);
  tmpListItem^.DetailDateTime := AStockDateTime;
  tmpListItem^.DetailData := ADetailData;
  try
    inherited InsertItem(Aindex, tmpListItem);
  except
    Dispose(tmpListItem);
    raise;
  end;
end;

{***************************************************************************}
function TDetailDataList.CompareItems(const Index1, Index2: integer): Integer;
var
  tmpItem1, tmpItem2: PDetailDataListItem;
begin
  tmpItem1 := PDetailDataListItem(Get(Index1));
  tmpItem2 := PDetailDataListItem(Get(Index2));
  result := tmpItem1^.DetailDateTime.Date.Value - tmpItem2^.DetailDateTime.Date.Value;
  if 0 = Result then
  begin
    result := tmpItem1^.DetailDateTime.Time.Value - tmpItem2^.DetailDateTime.Time.Value;
  end;
end;

{***********************************************************************}
function TDetailDataList.Find(AStockDateTime: TDateTimeStock; var AIndex: Integer): Boolean;
var
  L: Integer;
  H: Integer;
  I: Integer;
  C: double;
begin
  Result := False;
  L := 0;
  H := FCount - 1;
  while L <= H do
  begin
    I := (L + H) shr 1;
    C := Integer(GetItem(I)) - Integer(AStockDateTime);
    if C < 0 then
    begin
      L := I + 1
    end else
    begin
      H := I - 1;
      if C = 0 then
      begin
        Result := True;
        if Duplicates <> lstDupAccept then
          L := I;
      end;
    end;
  end;
  AIndex := L;
end;

{*******************************************************}
function TDetailDataList.GetItem(AIndex: Integer): TDateTimeStock;
begin
  Result := PDetailDataListItem(Get(Aindex))^.DetailDateTime;
end;

{******************************************************}
function TDetailDataList.IndexOf(AStockDateTime: TDateTimeStock): Integer;
begin
  if not Sorted then
  Begin
    Result := 0;
    while (Result < FCount) and (Integer(GetItem(result)) <> Integer(AStockDateTime)) do
    begin
      Inc(Result);
    end;
    if Result = FCount then
    begin
      Result := -1;
    end;
  end else if not Find(AStockDateTime, Result) then
    Result := -1;
end;
{*******************************************************************************************}
procedure TDetailDataList.InsertObject(AIndex: Integer; const AStockDateTime: TDateTimeStock; ADetailData: PRT_Quote_Detail);
var
  tmpListItem: PDetailDataListItem;
begin
  New(tmpListItem);
  tmpListItem^.DetailDateTime := AStockDateTime;
  tmpListItem^.DetailData := ADetailData;
  try
    inherited insert(Aindex, tmpListItem);
  except
    Dispose(tmpListItem);
    raise;
  end;
end;

{***********************************************************************}
procedure TDetailDataList.Notify(Ptr: Pointer; Action: TListNotification);
begin
  if Action = lstDeleted then
    dispose(ptr);
  inherited Notify(Ptr, Action);
end;

{********************************************************************}
procedure TDetailDataList.SetItem(AIndex: Integer; const AStockDateTime: TDateTimeStock);
var
  tmpListItem: PDetailDataListItem;
begin
  New(tmpListItem);
  tmpListItem^.DetailDateTime := AStockDateTime;
  tmpListItem^.DetailData := nil;
  Try
    Put(AIndex, tmpListItem);
  except
    Dispose(tmpListItem);
    raise;
  end;
end;

{*********************************************************}
function TDetailDataList.GetObject(AIndex: Integer): PRT_Quote_Detail;
begin
  if (AIndex < 0) or (AIndex >= FCount) then
    Error(@SALListIndexError, AIndex);
  Result :=  PDetailDataListItem(Get(Aindex))^.DetailData;
end;

{***************************************************************}
function TDetailDataList.IndexOfObject(ADetailData: PRT_Quote_Detail): Integer;
begin
  for Result := 0 to Count - 1 do
  begin
    if GetObject(Result) = ADetailData then
    begin
      Exit;
    end;
  end;
  Result := -1;
end;

{*******************************************************************}
procedure TDetailDataList.PutObject(AIndex: Integer; ADetailData: PRT_Quote_Detail);
begin
  if (AIndex < 0) or (AIndex >= FCount) then
  begin
    Error(@SALListIndexError, AIndex);
  end;
  PDetailDataListItem(Get(Aindex))^.DetailData := ADetailData;
end;

end.
